/*******************************************************************************
 *                                    ZLG
 *                         ----------------------------
 *                         innovating embedded platform
 *
 * Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
 * All rights reserved.
 *
 * Contact information:
 * web site:    https://www.zlg.cn
 *******************************************************************************/
#ifndef __WED_MEMHEAP2_H__
#define __WED_MEMHEAP2_H__

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "Wed_common.h"
#include "Wed_errno.h"
#include "print/wed_print.h"
#include "kernel/Wed_mutex.h"

/* \brief 魔法数 */
#define WED_MEMHEAP2_MAGIC             0x1ea01ea0
/* \brief 魔法数掩码 */
#define WED_MEMHEAP2_MAGIC_MASK        0xfffffffe
/* \brief 对齐大小 */
#define WED_MEMHEAP2_ALIGN_SIZE       (sizeof(void *))
/* \brief 内存堆条目大小 */
#define WED_MEMHEAP2_ITEM_SIZE         WED_ALIGN_UP(sizeof(struct Wed_memheap2_item), WED_MEMHEAP2_ALIGN_SIZE)
#define WED_MEMHEAP2_ITEM_USED         0x01
#define WED_MEMHEAP2_ITEM_FREED        0x00
/* \brief 内存堆条目是否被使用 */
#define WED_MEMHEAP2_ITEM_IS_USED(i) ((i)->magic & WED_MEMHEAP2_ITEM_USED)
/* \brief 内存堆最小分配内存大小 */
#define WED_MEMHEAP2_MINIALLOC         12

/* \brief 内存堆条目结构体 */
struct Wed_memheap2_item {
    uint32_t                   magic;             /* 内存单元的魔数，保护写越界 */
    struct Wed_memheap2       *p_mem_heap;        /* 堆内存的指针 */
    struct Wed_memheap2_item  *p_item_next;       /* 下一个内存单元 */
    struct Wed_memheap2_item  *p_item_prev;       /* 前一个内存单元 */
    struct Wed_memheap2_item  *p_item_free_next;  /* 下一个空闲的内存单元 */
    struct Wed_memheap2_item  *p_item_free_prev;  /* 前一个空闲的内存单元 */
};

/* \brief 内存堆信息结构体 */
struct Wed_memheap2 {
    void                     *p_start_addr;      /* 堆内存的起始地址 */
    uint32_t                  total_size;        /* 堆内存的大小 */
    uint32_t                  available_size;    /* 可用大小 */
    uint32_t                  max_used_size;     /* 分配的最大值 */
    struct Wed_memheap2_item *p_item_list;       /* 当前使用的单元链表 */
    struct Wed_memheap2_item *p_item_free_list;  /* 空闲单元链表 */
    struct Wed_memheap2_item  free_item_hdr;     /* 空闲块的链表头 */
    struct Wed_mutex          lock;              /* 互斥锁 */
};

/**
 * \brief 内存堆初始化
 *
 * @param p_mem_heap   要初始化的内存堆结构体
 * @param p_start_addr 内存起始地址
 * @param size         内存大小
 *
 * @return 成功返回 0
 */
int Wed_memheap2_init(struct Wed_memheap2 *p_mem_heap,
                      void                *p_start_addr,
                      uint32_t             size);
/**
 * \brief 堆内存分配
 *
 * @param p_mem_heap 堆信息结构体
 * @param size       要分配的大小
 *
 * @return 成功返回分配的内存地址
 */
void *Wed_memheap2_malloc(struct Wed_memheap2 *p_mem_heap, uint32_t size);
/**
 * \brief 堆内存释放
 *
 * @param p_mem 要释放的内存
 */
void Wed_memheap2_free(void *p_mem);
/**
 * \brief 堆内存地址对齐分配
 *
 * @param p_mem_heap 堆信息结构体
 * @param size       要分配的大小
 * @param align      地址对齐的数
 *
 * @return 成功返回分配的内存地址
 */
void *Wed_memheap2_align_malloc(struct Wed_memheap2 *p_mem_heap,
                                uint32_t             size,
                                uint32_t             align);
/**
 * \brief 堆对齐内存释放
 *
 * @param p_mem 要释放的内存
 */
void Wed_memheap2_align_free(void *p_mem);
#ifdef __cplusplus
}
#endif  /* __cplusplus  */
#endif


